using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Printing;
using System.IO;
using System.Drawing.Imaging;
using Microsoft.Reporting.WinForms;
using System.Runtime.InteropServices;
using System.Reflection;

namespace Billing.Reports
{
    public partial class ReportForm : Billing.WindowsBase.ReportFormBase
    {
        private int m_currentPageIndex;
        private bool mHideParameters = false;

        public bool HideParameters
        {
            get { return mHideParameters; }
            set { mHideParameters = value; }
        }

        private IList<Stream> m_streams;

        public ReportForm()
            : this(string.Empty)
        {

        }

        public ReportForm(string reportName)
            : base(reportName)
        {
            InitializeComponent();
        }

        protected override void OnLoadReport(EventArgs e)
        {
            this.reportViewer1.ProcessingMode = ProcessingMode;
            m_currentPageIndex = 0;
            Report report = null;
            this.reportViewer1.ShowParameterPrompts = !this.HideParameters;
            if (ProcessingMode == ProcessingMode.Local)
            {
                System.IO.Stream strm = Assembly.GetManifestResourceStream(ReportName);
                this.reportViewer1.LocalReport.LoadReportDefinition(strm);
                if (DataSource != null)
                {
                    ReportDataSource reportDataSource1 = new ReportDataSource();
                    reportDataSource1.Name = this.reportViewer1.LocalReport.GetDataSourceNames()[0];
                    reportDataSource1.Value = new BindingSource(DataSource, "");
                    this.reportViewer1.LocalReport.DataSources.Add(reportDataSource1);
                }

                report = this.reportViewer1.LocalReport;
            }
            else //ProcessingMode.Remote
            {
                //object obj = Activator.CreateInstance(typeof(ServerReport), true);
                //ServerReport SR = (ServerReport)obj;
                //SR.ReportServerUrl = new Uri(Billing.SettingManager.getSetting("ReportService"));
                //SR.ReportPath = ReportName;
                //SR.ReportServerCredentials.NetworkCredentials = new System.Net.NetworkCredential("administrator", "stb2007");

                this.reportViewer1.ServerReport.ReportServerUrl = new Uri(Billing.SettingManager.getSetting("ReportService"));
                this.reportViewer1.ServerReport.ReportPath = ReportName;
                this.reportViewer1.ServerReport.ReportServerCredentials.NetworkCredentials =
                    new System.Net.NetworkCredential(
                        Billing.SettingManager.getSetting("ReportServiceUser"),
                        Billing.SettingManager.getSetting("ReportServicePassword"));

                report = this.reportViewer1.ServerReport;
            }

            if (this.Parameters != null)
                report.SetParameters(Parameters);

            if (!this.PrintPreview)
            {
                Export(report);
                OnPrint(new CancelEventArgs(false));
            }

            reportViewer1.RefreshReport();
            base.OnLoadReport(e);
        }
       

        protected override void OnPrint(CancelEventArgs e)
        {
            base.OnPrint(e);
            if (!e.Cancel)
            {
                string printerName = new PrinterSettings().PrinterName;// "Microsoft Office Document Image Writer";
                if (m_streams == null || m_streams.Count == 0)
                    return;

                PrintDocument printDoc = new PrintDocument();
                printDoc.PrinterSettings.PrinterName = printerName;
                printDoc.PrintController = new StandardPrintController();

                if (!printDoc.PrinterSettings.IsValid)
                {
                    string msg = String.Format("Can't find printer \"{0}\".", printerName);
                    MessageBox.Show(msg, "Print Error");
                    return;
                }

                printDoc.PrintPage += new PrintPageEventHandler(PrintPage);
                printDoc.EndPrint += new PrintEventHandler(printDoc_EndPrint);
                printDoc.Print();
            }
        }

        private void reportViewer1_Print(object sender, CancelEventArgs e)
        {
            if (this.InnerPrintEngine)
                return;
            try
            {
                this.Cursor = Cursors.WaitCursor;

                e.Cancel = true;
                if (ProcessingMode == ProcessingMode.Local)
                {
                    Export(this.reportViewer1.LocalReport);
                }
                else
                {
                    Export(this.reportViewer1.ServerReport);
                }

                m_currentPageIndex = 0;
                OnPrint(new CancelEventArgs(false));
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            finally
            {
                this.Cursor = Cursors.Default;
            }
        }

        void printDoc_EndPrint(object sender, PrintEventArgs e)
        {
            if (m_streams != null)
            {
                foreach (Stream stream in m_streams)
                    stream.Close();
                m_streams = null;
            }
        }

        private void Export(Report report)
        {
            string deviceInfo;
            deviceInfo =
            "<DeviceInfo>" +
            "  <OutputFormat>EMF</OutputFormat>" +
            "</DeviceInfo>";

            Warning[] warnings;
            string mimeType;
            string encoding;
            string fileNameExtencion;
            string[] streams;
            m_streams = new List<Stream>();
            int m_numberOfPages;

            byte[] buffer = report.Render("Image", deviceInfo, out mimeType, out encoding, out fileNameExtencion, out streams, out warnings);

            m_numberOfPages = streams.Length + 1;
            CreateStream(buffer);

            for (int pageIndex = 1; pageIndex < m_numberOfPages; pageIndex++)
            {
                deviceInfo =
                String.Format(@"<DeviceInfo><OutputFormat>{0}</OutputFormat><StartPage>{1}</StartPage></DeviceInfo>", "emf", pageIndex + 1);
                buffer = null;
                buffer = report.Render("Image", deviceInfo, out mimeType, out encoding, out fileNameExtencion, out streams, out warnings);
                CreateStream(buffer);
            }
            foreach (Stream s in m_streams)
            {
                s.Seek(0, SeekOrigin.Begin);
            }
        }
        private Stream CreateStream()
        {
            return CreateStream(null);
        }
        private Stream CreateStream(byte[] buffer)
        {
            Stream stream = null;
            if (buffer == null)
            {
                stream = new MemoryStream();
            }
            else
            {
                stream = new MemoryStream(buffer);
            }

            m_streams.Add(stream);
            return stream;
        }

        private void PrintPage(object sender, PrintPageEventArgs ev)
        {
     
            Metafile pageImage = new Metafile(m_streams[m_currentPageIndex]);
            ev.Graphics.DrawImage(pageImage, ev.PageBounds);
            m_currentPageIndex++;
            ev.HasMorePages = (m_currentPageIndex < m_streams.Count);

        }

        private void frmReportView_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (m_streams != null)
            {
                foreach (Stream stream in m_streams)
                {
                    stream.Close();
                }
                m_streams = null;
            }
        }

        private void btnClose_Click(object sender, EventArgs e)
        {
            this.Close();
        }
    }
}